﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Bson;
using MongoExplorerTool.Infra.Connection;

namespace MongoExplorerTool.Model
{
    public class Database : IRefreshable
    {
        #region Properties
        public string Name { get; private set; }
        public DatabaseStats DatabaseStats { get; private set; }
        public MongoDatabase MongoDatabase { get; private set; }

        public IEnumerable<Collection> Collections { get; private set; }
        #endregion Properties

        #region Constructors
        public Database(MongoDatabase mongoDatabase)
        {
            this.MongoDatabase = mongoDatabase;
            this.Refresh();
        }
        #endregion Constructors

        #region Static Methods
        private static string CreateConnectionString(ConnectionInfo connectionInfo)
        {
            if (!connectionInfo.IsValid())
                throw new InvalidConnectionInfoException();

            string usernamePassword = string.Empty;
            if (!string.IsNullOrWhiteSpace(connectionInfo.Username))
                usernamePassword = string.Format("{0}:{1}@", connectionInfo.Username, connectionInfo.Password);

            string serverPort;
            if (!string.IsNullOrWhiteSpace(connectionInfo.Port))
                serverPort = string.Format("{0}:{1}", connectionInfo.Server, connectionInfo.Port);
            else
                serverPort = connectionInfo.Server;

            return string.Format("mongodb://{0}{1}/?safe=true", usernamePassword, serverPort);
        }

        public static IEnumerable<Database> List(ConnectionInfo connectionInfo)
        {
            string connectionString = CreateConnectionString(connectionInfo);
            var server = MongoServer.Create(connectionString);
            var databaseNames = server.GetDatabaseNames();
            foreach (var databaseName in databaseNames)
                yield return new Database(server.GetDatabase(databaseName));
        }
        #endregion Static Methods

        #region Instance Methods
        public DatabaseStats GetDatabaseStats()
        {
            var mongoStats = this.MongoDatabase.GetStats();

            var databaseStats = new DatabaseStats();
            databaseStats.CollectionCount = mongoStats.CollectionCount;
            databaseStats.DataSize = mongoStats.DataSize;
            databaseStats.FileSize = mongoStats.FileSize;
            databaseStats.StorageSize = mongoStats.StorageSize;

            return databaseStats;
        }

        private IEnumerable<Collection> GetCollections()
        {
            var colectionNames = this.MongoDatabase.GetCollectionNames();
            foreach (var colectionName in colectionNames)
                yield return new Collection(this.MongoDatabase.GetCollection(colectionName));
        }

        public void Refresh()
        {
            this.Name = this.MongoDatabase.Name;
            this.DatabaseStats = this.GetDatabaseStats();
            this.Collections = this.GetCollections();
        }
        #endregion Instance Methods
    }
}
